
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "SquareButton.h"
#include <QtGui>
#include <QFont>
#include <QTextStream>
#include <fstream>
#include <time.h>

#include "mainwindow.h"
char *val1,*val2;
char op='0';
int FCount = 33;
int TooltipCount = 1;
QString Mem;
QString S = "";
bool Logging = false;
bool LogDone = true;
int lineSize=0;
fstream out;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    QKeyEvent * KeyEvent = new QKeyEvent(QEvent::KeyPress,0x2b,0,0,0,0);

    fileMenu = new QMenu;
    fileMenu->setFocusPolicy(Qt::NoFocus);
    createActions();
    createMenus();
    createStatusBar();
    QVBoxLayout *vert = new QVBoxLayout;
    QWidget *centralWidget = new QWidget();
    centralWidget->setLayout(vert);
    this->setCentralWidget(centralWidget);

    //Buttons
    SquareButton *one = new SquareButton("1");
    SquareButton *two = new SquareButton("2");
    SquareButton *three = new SquareButton("3");
    SquareButton *four = new SquareButton("4");
    SquareButton *five = new SquareButton("5");
    SquareButton *six = new SquareButton("6");
    SquareButton *seven = new SquareButton("7");
    SquareButton *eight = new SquareButton("8");
    SquareButton *nine = new SquareButton("9");
    SquareButton *zero = new SquareButton("0");
    SquareButton *threezeros = new SquareButton("000");

    //top Layout
    Memory = new QLineEdit;
    Memory->setAlignment(Qt::AlignCenter);
    Memory->setReadOnly(true);
    Memory->setEnabled(false);
    Memory->setBaseSize(50,50);
    Memory->setMinimumSize(50,50);
    Memory->setMaximumSize(50,50);
    Memory->setFocusPolicy(Qt::NoFocus);
    QFont F;
    F.setPointSize(20);
    Memory->setFont(F);
    QPushButton *backspace = new QPushButton("Backspace");
    backspace->setMinimumSize(85,40);
    backspace->setMaximumSize(85,40);
    backspace->setFocusPolicy(Qt::NoFocus);
    QPushButton *clear = new QPushButton("C");
    clear->setMinimumSize(85,40);
    clear->setMaximumSize(85,40);
    clear->setFocusPolicy(Qt::NoFocus);
    QPushButton *ce = new QPushButton("CE");
    ce->setMinimumSize(85,40);
    ce->setMaximumSize(85,40);
    ce->setFocusPolicy(Qt::NoFocus);
    //memory
    SquareButton *MC = new SquareButton("MC");
    SquareButton *MR = new SquareButton("MR");
    SquareButton *Mplus = new SquareButton("M+");
    SquareButton *MS = new SquareButton("MS");
    //actions
    SquareButton *plus = new SquareButton("+");
    SquareButton *minus = new SquareButton("-");
    SquareButton *multiply = new SquareButton("*");
    SquareButton *equal = new SquareButton("=");
    SquareButton *div = new SquareButton("/");
    SquareButton *squared = new SquareButton("x^2");
    SquareButton *cubed = new SquareButton("x^3");
    SquareButton *power = new SquareButton("x^y");
    SquareButton *mod = new SquareButton("%");



    QGridLayout *mLayout = new QGridLayout;
    QHBoxLayout *HBoxLayout = new QHBoxLayout;
    QHBoxLayout *BCLayout = new QHBoxLayout;
    //add layouts
    vert->addLayout(HBoxLayout);
    vert->addLayout(BCLayout);
    vert->addLayout(mLayout);
    //add buttons
    BCLayout->addWidget(Memory);
    BCLayout->addWidget(backspace);
    BCLayout->addWidget(ce);
    BCLayout->addWidget(clear);

    mLayout->addWidget(MC,1,1);
    mLayout->addWidget(MR,2,1);
    mLayout->addWidget(MS,3,1);
    mLayout->addWidget(Mplus,4,1);
    mLayout->addWidget(seven,1,2);
    mLayout->addWidget(four,2,2);
    mLayout->addWidget(one,3,2);
    mLayout->addWidget(zero,4,2);
    mLayout->addWidget(eight,1,3);
    mLayout->addWidget(five,2,3);
    mLayout->addWidget(two,3,3);
    mLayout->addWidget(threezeros,4,3);
    mLayout->addWidget(nine,1,4);
    mLayout->addWidget(six,2,4);
    mLayout->addWidget(three,3,4);
    mLayout->addWidget(equal,4,4);
//actions
    mLayout->addWidget(div,1,5);
    mLayout->addWidget(multiply,1,6);
    mLayout->addWidget(mod,2,5);
    mLayout->addWidget(squared,2,6);
    mLayout->addWidget(plus,3,5);
    mLayout->addWidget(cubed,3,6);
    mLayout->addWidget(minus,4,5);
    mLayout->addWidget(power,4,6);

    Line = new QLineEdit();
    Line->setAlignment(Qt::AlignRight);
    s.setPointSize(14);
    Line->setFont(s);
    //Line->setDisabled(true);
    QRegExp rx( "^[-]{0,1}[1-9]{1}[0-9]*$" );
    QValidator *validator = new QRegExpValidator(rx, this);
    Line->setFocus();
//    connect(Line,SIGNAL(QEvent::FocusOut),this,SLOT(Line->setFocus()));
    Line->setValidator( validator );
   // Line->setToolTip(Line->text());
    //connect(Line,SIGNAL(textChanged(QString)),this, SLOT(CheckFont()));
    HBoxLayout->addWidget(Line);

    //setting connections

    connect(one,SIGNAL(clicked()),this,SLOT(one()));
    connect(two,SIGNAL(clicked()),this,SLOT(two()));
    connect(three,SIGNAL(clicked()),this,SLOT(three()));
    connect(four,SIGNAL(clicked()),this,SLOT(four()));
    connect(five,SIGNAL(clicked()),this,SLOT(five()));
    connect(six,SIGNAL(clicked()),this,SLOT(six()));
    connect(seven,SIGNAL(clicked()),this,SLOT(seven()));
    connect(eight,SIGNAL(clicked()),this,SLOT(eight()));
    connect(nine,SIGNAL(clicked()),this,SLOT(nine()));
    connect(zero,SIGNAL(clicked()),this,SLOT(zero()));
    connect(threezeros,SIGNAL(clicked()),this,SLOT(threezeros()));
    connect(clear,SIGNAL(clicked()),this,SLOT(clear()));
    connect(ce,SIGNAL(clicked()),this,SLOT(CE()));
    connect(backspace,SIGNAL(clicked()),this,SLOT(Backspace()));

    connect(plus,SIGNAL(clicked()),this,SLOT(plus()));
    connect(minus,SIGNAL(clicked()),this,SLOT(minus()));
    connect(multiply,SIGNAL(clicked()),this,SLOT(multiply()));
    connect(equal,SIGNAL(clicked()),this,SLOT(equal()));
    connect(squared,SIGNAL(clicked()),this, SLOT(Squared()));
    connect(cubed,SIGNAL(clicked()),this, SLOT(Cubed()));
    connect(power,SIGNAL(clicked()),this,SLOT(Power()));
    connect(div,SIGNAL(clicked()),this,SLOT(div()));
    connect(mod,SIGNAL(clicked()),this,SLOT(mod()));

    connect(MR,SIGNAL(clicked()),this,SLOT(MR()));
    connect(MC,SIGNAL(clicked()),this,SLOT(MC()));
    connect(Mplus,SIGNAL(clicked()),this,SLOT(Mplus()));
    connect(MS,SIGNAL(clicked()),this,SLOT(MS()));

    connect(exitAct, SIGNAL(triggered()), this, SLOT(Exit()));
}


MainWindow::~MainWindow()
{
}

void MainWindow::one()
{
    if (Line->text() != "0")
    Line->setText(Line->text() + "1");
    else Line->setText("1");
}
void MainWindow::two()
{
    if (Line->text() != "0")
    Line->setText(Line->text() + "2");
    else Line->setText("2");
}

void MainWindow::three()
{
    if (Line->text() != "0")
    Line->setText(Line->text() + "3");
    else Line->setText("3");
}

void MainWindow::four()
{
    if (Line->text() != "0")
    Line->setText(Line->text() + "4");
    else Line->setText("4");
}

void MainWindow::five()
{
    if (Line->text() != "0")
    Line->setText(Line->text() + "5");
    else Line->setText("5");
}

void MainWindow::six()
{
    if (Line->text() != "0")
    Line->setText(Line->text() + "6");
    else Line->setText("6");
}

void MainWindow::seven()
{
    if (Line->text() != "0")
    Line->setText(Line->text() + "7");
    else Line->setText("7");
}

void MainWindow::eight()
{
    if (Line->text() != "0")
    Line->setText(Line->text() + "8");
    else Line->setText("8");
}

void MainWindow::nine()
{
    if (Line->text() != "0")
    Line->setText(Line->text() + "9");
    else Line->setText("9");
}

void MainWindow::zero()
{
    if (Line->text() != "")
    Line->setText(Line->text() + "0");
}

void MainWindow::threezeros()
{
    if (Line->text() != "")
    Line->setText(Line->text() + "000");
}


void MainWindow::clear()
{
    Line->setText("");
    S = "";
    Line->setToolTip("");
    LogDone = true;
}

void MainWindow::Backspace()
{
    Line->backspace();
}

void MainWindow::CE()
{
    Line->setText("");
    S = "";
    Line->setToolTip("");
    val1 = "";
    val2 = "";
    Mem = "";
    Memory->setText("");
}

/*void MainWindow::CheckFont()
{
    if (Line->text().length() == FCount)
    {
        s.setPointSize(s.pointSize()-1);
        Line->setFont(s);
        FCount+=5;
    }
}*/
void MainWindow::UpdateToolTip()
{
    if ( lineSize+1!=Line->text().length() && lineSize-1!=Line->text().length())
    {
        lineSize=Line->text().length();
        NewToolTip();
        return;
    }
    if (Line->text().length() - 1 == S.length())
    S.append(Line->text()[Line->text().length()-1]);
    else if(Line->text().length() == S.length()-1)
    S.resize(S.length()-1);
    if (Line->text().length()-200*TooltipCount == 0)
    {
        TooltipCount++;
        S.append('\n');
    }
    Line->setToolTip(S);
}
//-------MEMORY--------------
void MainWindow::MC()
{
    Mem = "";
    Memory->setText("");
}
void MainWindow::MR()
{
    if (Mem != "")
    MainWindow::Line->setText(Mem);
}
void MainWindow::MS()
{
    if (Line->text() != "")
    {
        Mem = Line->text();
        Memory->setText("M");
    }
}
void MainWindow::Mplus()
{
   if (Mem != "")
   {
   char * temp = qstrdup(Line->text().toAscii().constData());
   char * _temp = qstrdup(Mem.toAscii().constData());
   byte *val3;
   LongNum a,b;
   a.SetVal(temp); b.SetVal(_temp);
   a += b;
   val3 = a.GetVal();
   Mem = "";
   QTextStream os( &Mem);
   for(uint i=0; i<a.GetLength(); i++)
   os << (char)val3[i];
   connect(Line,SIGNAL(textChanged(const QString)),this,SLOT(nul()));
   }
   else MS();
}

//-------ACTIONS--------------
void MainWindow::plus()
{
    val1 = qstrdup(Line->text().toAscii().constData());
    op = '+';
    if (LogDone)
    {
        out << val1;
        out<< " " << '+' << " ";
        LogDone = false;
    }
    connect(Line,SIGNAL(textChanged(const QString)),this,SLOT(nul()));
}

void MainWindow::minus()
{
    if (Line->text() == "") Line->setText("-");
    else
    {
        val1 = qstrdup(Line->text().toAscii().constData());
        op = '-';
        if (LogDone)
        {
            out << val1;
            out<< " " << '-' << " ";
            LogDone = false;
        }
        connect(Line,SIGNAL(textChanged(const QString)),this,SLOT(nul()));
    }
}

void MainWindow::div()
{
    val1 = qstrdup(Line->text().toAscii().constData());
    op = '/';
    if (LogDone)
    {
        out << val1;
        out<< " " << '/' << " ";
        LogDone = false;
    }
    connect(Line,SIGNAL(textChanged(const QString)),this,SLOT(nul()));
}

void MainWindow::mod()
{
    val1 = qstrdup(Line->text().toAscii().constData());
    op = '%';
    if (LogDone)
    {
        out << val1;
        out<< " " << '%' << " ";
        LogDone = false;
    }
    connect(Line,SIGNAL(textChanged(const QString)),this,SLOT(nul()));
}

void MainWindow::multiply()
{
    val1 = qstrdup(Line->text().toAscii().constData());
    op = '*';
    if (LogDone)
    {
        out << val1;
        out<< " " << '*' << " ";
        LogDone = false;
    }
    connect(Line,SIGNAL(textChanged(const QString)),this,SLOT(nul()));
}


void MainWindow::nul()
{
    int length = Line->text().length();
    QString mid = Line->text().mid(length-1,1);
    Line->disconnect();
    Line->setText(mid);
}
void MainWindow::Squared()
{
    Line->disconnect();
    val1 = qstrdup(Line->text().toAscii().constData());
    LongNum a;
    a.SetVal(val1);
    a *= a;
    byte *val3 = a.GetVal();
    QString res;
    QTextStream os( &res);
    for(uint i=0; i<a.GetLength(); i++)
    os << (char)val3[i];
    Line->setText(res);
    out << val1 << "^2 = " << val3 << endl;
    NewToolTip();
    connect(Line,SIGNAL(textChanged(const QString)),this,SLOT(nul()));
}

void MainWindow::Cubed()
{
    Line->disconnect();
    val1 = qstrdup(Line->text().toAscii().constData());
    LongNum a;
    a.SetVal(val1);
    a = a*a*a;
    byte *val3 = a.GetVal();
    QString res;
    QTextStream os( &res);
    for(uint i=0; i<a.GetLength(); i++)
    os << (char)val3[i];
    Line->setText(res);
    out << val1 << "^2 = " << val3 << endl;
    NewToolTip();
    connect(Line,SIGNAL(textChanged(const QString)),this,SLOT(nul()));
}

void MainWindow::Power()
{
    val1 = qstrdup(Line->text().toAscii().constData());
    op = '^';
    connect(Line,SIGNAL(textChanged(const QString)),this,SLOT(nul()));
    NewToolTip();
}

void MainWindow::equal()
{
    Line->disconnect();
    if (op == '0') return;
    val2 = qstrdup(Line->text().toAscii().constData());
    byte *val3;
    LongNum a,b;
    a.SetVal(val1); b.SetVal(val2);
    switch ((int)op)
    {
    case (int)'+':{
        a+=b;
        break;
    }
    case (int)'-':{
        a-=b;
        break;
    }
    case (int)'*':{
        a*=b;
        break;
    }
    case (int)'/':{
        a/=b;
        break;
    }
    case (int)'%':{
        a%=b;
        break;
    }
    case (int)'^':
        { break;}
    }
    val3 = a.GetVal();
    QString res;
    QTextStream os( &res);
    if (!a.GetSign()) os<<'-';
    for(uint i=0; i<a.GetLength(); i++)
    os << (char)val3[i];
    Line->setText(res);
    connect(Line,SIGNAL(textChanged(const QString)),this,SLOT(nul()));
    op = '0';
    out << val2 << " = " << res.toStdString() << endl;
    LogDone = true;
    NewToolTip();
}
void MainWindow::createMenus()
{
        fileMenu = menuBar()->addMenu(tr("&File"));
        fileMenu->addAction(newAct);
        fileMenu->addAction(openAct);
        fileMenu->addSeparator();
        fileMenu->addAction(exitAct);

        editMenu = menuBar()->addMenu(tr("&Functions"));
        menuBar()->addSeparator();

        helpMenu = menuBar()->addMenu(tr("&?"));
        helpMenu->addAction(aboutAct);
}

void MainWindow::createActions()
 {
     newAct = new QAction(tr("&Start logging"), this);
     newAct->setShortcuts(QKeySequence::New);
     newAct->setStatusTip(tr("Start a log"));
     connect(newAct,SIGNAL(triggered()),this,SLOT(startLog()));

     openAct = new QAction(tr("&Stop logging"), this);
     openAct->setShortcuts(QKeySequence::Open);
     openAct->setStatusTip(tr("Stop current log"));
     connect(openAct,SIGNAL(triggered()),this, SLOT(stopLog()));

     exitAct = new QAction(tr("E&xit"), this);
     exitAct->setShortcuts(QKeySequence::Quit);
     exitAct->setStatusTip(tr("Exit the application"));

     aboutAct = new QAction(tr("&About"), this);
     aboutAct->setStatusTip(tr("Show the application's About box"));
 }
void MainWindow::startLog()
{
    if (!Logging)
    {
        char * filename = "C:/1/CalcLog.txt";
        out.open(filename);
        char dateStr [9];
        char timeStr [9];
        _strtime( timeStr );
        out<<"Time: "<<timeStr<<" ";
        _strdate( dateStr);
        out<<"Date: "<<dateStr<<"\n";
        QString buf(filename);
        statusBar()->showMessage("Recording log to " + buf,0);
        Logging = true;

    }
    else
    {
        out.close();
        statusBar()->showMessage("Logging stopped",0);
        Logging = false;

    }
}

void MainWindow::stopLog()
{
    if (Logging)
    MainWindow::startLog();
}

void MainWindow::createStatusBar()
{
    statusBar()->showMessage("Ready");
}

void MainWindow::NewToolTip()
{
    S = Line->text();
    for(int i=200; i<S.length()-1; i+=200)
        S.insert(i,"\n");
    Line->setToolTip(S);
}

void MainWindow::setFocusBegin()
{
    Line->setCursorPosition(Line->text().length());
}

void MainWindow::Exit()
{
    qApp->quit();
}

/*void QLineEdit::keyPressEvent(QKeyEvent *event)
{
    //QMainWindow::keyPressEvent(event);
    switch (event->key())
    {
    case Qt::Key_Left:
        minus();
        break;
    case Qt::Key_Plus:
        plus();
        break;
    case Qt::Key_multiply:
        //multiply();
        break;
    //QMainWindow::keyPressEvent(event);
    }
}*/

#endif
